package cs.study.height.concurrent018;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;


public class UseThreadPoolExecutor1 {


	public static void main(String[] args) {
		/*
		new ThreadPoolExecutor(
			int corePoolSize,	当前核心线程数
			int maximumPoolSize,最大线程数
			long keepAliveTime, 线程池里面的线程空闲时间
			TimeUnit unit,      keepAliveTime的时间单位
			BlockingQueue<Runnable> workQueue, 没有空闲的线程时，用于存放任务
			ThreadFactory threadFactory,
			RejectedExecutionHandler headler 拒绝执行任务
			) {....}
		*/
		/**
		 * 在使用有界队列时，若有新的任务需要执行，如果线程池实际线程数小于corePoolSize，则优先创建线程，
		 * 若大于corePoolSize，则会将任务加入队列，
		 * 若队列已满，则在总线程数不大于maximumPoolSize的前提下，创建新的线程，
		 * 若线程数大于maximumPoolSize，则执行拒绝策略。或其他自定义方式。
		 * 
		 */	
		ThreadPoolExecutor pool = new ThreadPoolExecutor(
				1, 				//coreSize
				2, 				//MaxSize
				60, 			//60
				TimeUnit.SECONDS, 
				new ArrayBlockingQueue<Runnable>(3)			//指定一种队列 （有界队列）
				//new LinkedBlockingQueue<Runnable>()
				, new MyRejected()
				//, new ThreadPoolExecutor.DiscardOldestPolicy()
				);
		
		MyTask mt1 = new MyTask(1, "任务1");
		MyTask mt2 = new MyTask(2, "任务2");
		MyTask mt3 = new MyTask(3, "任务3");
		MyTask mt4 = new MyTask(4, "任务4");
		MyTask mt5 = new MyTask(5, "任务5");
		MyTask mt6 = new MyTask(6, "任务6");
		
		pool.execute(mt1);
		pool.execute(mt2);
		pool.execute(mt3);
		pool.execute(mt4);
		pool.execute(mt5);
		pool.execute(mt6);
		
		pool.shutdown();
		/**
		 运行结果：
		 run taskId =1
		 run taskId =5
		 run taskId =3
		 run taskId =4
		 run taskId =6

		 分析：
		 使用有界阻塞队列，先为1开启一个核心线程，然后为2 3 4入队，然后
		 为5开启一个线程（最大线程），本来应该是舍弃6，但是指定了舍弃策略
		 是舍弃最老的，也就是阻塞队列队头元素2，所以舍弃2而执行6

		 如果自定义舍弃策略：
		 一般不要给用户浏览器反馈信息，因为此时系统负荷非常严重，如果此时要
		 拒绝10000个队列，系统根本没有这么多资源，所以实际项目中就是把taskID
		 记载到log日志中就可以了。

		 如果使用无界队列很简单，开启核心线程数，多余的全部阻塞直到内存耗尽。
		 如果使用有界队列，要清楚工作流程：
		 若有新的任务需要执行，如果线程池实际线程数小于corePoolSize，则优先创建线程，
		 若大于corePoolSize，则会将任务加入队列，
		 若队列已满，则在总线程数不大于maximumPoolSize的前提下，创建新的线程，
		 若线程数大于maximumPoolSize，则执行拒绝策略。或其他自定义方式。

		 */
		
	}
}
